/**
 * Copyright 2020 jianggujin (www.jianggujin.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jianggujin.dbfly.mybatis;

import com.jianggujin.dbfly.util.dtd.JDTD;
import com.jianggujin.dbfly.util.dtd.JDTDAttribute;
import com.jianggujin.dbfly.util.dtd.JDTDCardinal;
import com.jianggujin.dbfly.util.dtd.JDTDDecl;
import com.jianggujin.dbfly.util.dtd.JDTDElement;
import com.jianggujin.dbfly.util.dtd.JDTDEmpty;
import com.jianggujin.dbfly.util.dtd.JDTDEnumeration;
import com.jianggujin.dbfly.util.dtd.JDTDItem;
import com.jianggujin.dbfly.util.dtd.JDTDName;
import com.jianggujin.dbfly.util.dtd.JDTDSequence;

/**
 * JDBFly的Config的DTD验证，对Mybatis的DTD进行了扩展
 * 
 * @author jianggujin
 *
 */
public class JDBFlyConfigDTDFactory implements JDBFlyDTDFactory {
    @Override
    public JDTD createDTD() {
        JDTD dtd = new JDTD();
        // <!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?,
        // objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?,
        // environments?, databaseIdProvider?, mappers?)>
        JDTDItem empty = new JDTDEmpty();
        JDTDSequence configurationContent = new JDTDSequence(JDTDCardinal.NONE, JDTDCardinal.OPTIONAL, "properties",
                "settings", "typeAliases", "typeHandlers", "objectFactory", "objectWrapperFactory", "reflectorFactory",
                "plugins", "environments", "databaseIdProvider", "mappers");
        dtd.add(new JDTDElement("configuration", configurationContent).withComment("配置"));

        // <!ELEMENT databaseIdProvider (property*)>
        // <!ATTLIST databaseIdProvider
        // type CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("databaseIdProvider", new JDTDName("property", JDTDCardinal.ZEROMANY),
                new JDTDAttribute("type", "CDATA", JDTDDecl.REQUIRED)).withComment("数据库厂商标识"));

        // <!ELEMENT properties (property*)>
        // <!ATTLIST properties
        // resource CDATA #IMPLIED
        // url CDATA #IMPLIED
        // >
        dtd.add(new JDTDElement("properties", new JDTDName("property", JDTDCardinal.ZEROMANY), "resource", "url")
                .withComment("属性"));

        // <!ELEMENT property EMPTY>
        // <!ATTLIST property
        // name CDATA #REQUIRED
        // value CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("property", empty, new JDTDAttribute("name", "CDATA", JDTDDecl.REQUIRED),
                new JDTDAttribute("value", "CDATA", JDTDDecl.REQUIRED)));

        // <!ELEMENT settings (setting+)>
        dtd.add(new JDTDElement("settings", new JDTDName("setting", JDTDCardinal.ONEMANY)));

        // <!ELEMENT setting EMPTY>
        // <!ATTLIST setting
        // name CDATA #REQUIRED
        // value CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("setting", empty, new JDTDAttribute("name", "CDATA", JDTDDecl.REQUIRED),
                new JDTDAttribute("value", "CDATA", JDTDDecl.REQUIRED)));

        // <!ELEMENT typeAliases (typeAlias*,package*)>
        dtd.add(new JDTDElement("typeAliases",
                new JDTDSequence(JDTDCardinal.NONE, JDTDCardinal.ZEROMANY, "typeAlias", "package")));

        // <!ELEMENT typeAlias EMPTY>
        // <!ATTLIST typeAlias
        // type CDATA #REQUIRED
        // alias CDATA #IMPLIED
        // >
        dtd.add(new JDTDElement("typeAlias", empty, new JDTDAttribute("type", "CDATA", JDTDDecl.REQUIRED),
                new JDTDAttribute("alias")));

        // <!ELEMENT typeHandlers (typeHandler*,package*)>
        dtd.add(new JDTDElement("typeHandlers",
                new JDTDSequence(JDTDCardinal.NONE, JDTDCardinal.ZEROMANY, "typeHandler", "package")));

        // <!ELEMENT typeHandler EMPTY>
        // <!ATTLIST typeHandler
        // javaType CDATA #IMPLIED
        // jdbcType CDATA #IMPLIED
        // handler CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("typeHandler", empty, new JDTDAttribute("javaType"), new JDTDAttribute("jdbcType"),
                new JDTDAttribute("handler", "CDATA", JDTDDecl.REQUIRED)));

        // <!ELEMENT objectFactory (property*)>
        // <!ATTLIST objectFactory
        // type CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("objectFactory", new JDTDName("property", JDTDCardinal.ZEROMANY),
                new JDTDAttribute("type", "CDATA", JDTDDecl.REQUIRED)));

        // <!ELEMENT objectWrapperFactory EMPTY>
        // <!ATTLIST objectWrapperFactory
        // type CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("objectWrapperFactory", empty, new JDTDAttribute("type", "CDATA", JDTDDecl.REQUIRED)));

        // <!ELEMENT reflectorFactory EMPTY>
        // <!ATTLIST reflectorFactory
        // type CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("reflectorFactory", empty, new JDTDAttribute("type", "CDATA", JDTDDecl.REQUIRED)));

        // <!ELEMENT plugins (plugin+)>
        dtd.add(new JDTDElement("plugins", new JDTDName("plugin", JDTDCardinal.ONEMANY)));

        // <!ELEMENT plugin (property*)>
        // <!ATTLIST plugin
        // interceptor CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("plugin", new JDTDName("property", JDTDCardinal.ZEROMANY),
                new JDTDAttribute("interceptor", "CDATA", JDTDDecl.REQUIRED)));

        // <!ELEMENT environments (environment+)>
        // <!ATTLIST environments
        // default CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("environments", new JDTDName("environment", JDTDCardinal.ONEMANY),
                new JDTDAttribute("default", "CDATA", JDTDDecl.REQUIRED)));

        // <!ELEMENT environment (transactionManager,dataSource)>
        // <!ATTLIST environment
        // id CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("environment", new JDTDSequence("transactionManager", "dataSource"),
                new JDTDAttribute("id", "CDATA", JDTDDecl.REQUIRED)));

        // <!ELEMENT transactionManager (property*)>
        // <!ATTLIST transactionManager
        // type CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("transactionManager", new JDTDName("property", JDTDCardinal.ZEROMANY),
                new JDTDAttribute("type", "CDATA", JDTDDecl.REQUIRED)));

        // <!ELEMENT dataSource (property*)>
        // <!ATTLIST dataSource
        // type CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("dataSource", new JDTDName("property", JDTDCardinal.ZEROMANY),
                new JDTDAttribute("type", "CDATA", JDTDDecl.REQUIRED)));

        // <!ELEMENT mappers (mapper*,package*)>
        dtd.add(new JDTDElement("mappers",
                new JDTDSequence(JDTDCardinal.NONE, JDTDCardinal.ZEROMANY, "mapper", "package")));

        // <!ELEMENT mapper EMPTY>
        // <!ATTLIST mapper
        // resource CDATA #IMPLIED
        // url CDATA #IMPLIED
        // class CDATA #IMPLIED
        // >
        dtd.add(new JDTDElement("mapper", empty, "resource", "url", "class"));

        // <!ELEMENT package EMPTY>
        // <!ATTLIST package
        // name CDATA #REQUIRED
        // >
        dtd.add(new JDTDElement("package", empty, new JDTDAttribute("name", "CDATA", JDTDDecl.REQUIRED)));

        // 自定义元素
        configurationContent.add(JDTDCardinal.OPTIONAL, "dbfly");
        dtd.add(new JDTDElement("dbfly",
                new JDTDSequence(JDTDCardinal.NONE, JDTDCardinal.OPTIONAL, "dialect", "style", "useJavaType",
                        "notEmpty", "exludeSelects", "excludeInserts", "excludeUpdates", "valueGeneratorProperties",
                        "valueGeneratorClass")));
        dtd.add(new JDTDElement("dialect", empty, new JDTDAttribute("name", "CDATA", JDTDDecl.REQUIRED)));
        dtd.add(new JDTDElement("style", empty,
                new JDTDAttribute("name", new JDTDEnumeration("normal", "camelhump", "uppercase", "lowercase",
                        "camelhumpAndUppercase", "camelhumpAndLowercase"), JDTDDecl.VALUE, "camelhump")));
        dtd.add(new JDTDElement("useJavaType", empty,
                new JDTDAttribute("value", new JDTDEnumeration("true", "false"), JDTDDecl.VALUE, "false")));
        dtd.add(new JDTDElement("notEmpty", empty,
                new JDTDAttribute("value", new JDTDEnumeration("true", "false"), JDTDDecl.VALUE, "false")));
        dtd.add(new JDTDElement("exludeSelects", empty, new JDTDAttribute("property", "CDATA", JDTDDecl.REQUIRED)));
        dtd.add(new JDTDElement("excludeInserts", empty, new JDTDAttribute("property", "CDATA", JDTDDecl.REQUIRED)));
        dtd.add(new JDTDElement("excludeUpdates", empty, new JDTDAttribute("property", "CDATA", JDTDDecl.REQUIRED)));
        dtd.add(new JDTDElement("valueGeneratorProperties", empty,
                new JDTDAttribute("property", "CDATA", JDTDDecl.REQUIRED)));
        dtd.add(new JDTDElement("valueGeneratorClass", empty, new JDTDAttribute("name", "CDATA", JDTDDecl.REQUIRED)));
        return dtd;
    }
}
